/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wargame.controller;

import java.util.ArrayList;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import module.Analytic;
import module.GameTurn;
import module.GlobalConstant;
import module.ManageBid;
import module.ManageEmployee;
import module.ManagePlayer;
import module.ManageProject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import wargame.dao.BidDAO;
import wargame.dao.EmployeeDAO;
import wargame.dao.OutsourceProjectDAO;
import wargame.dao.PlayerDAO;
import wargame.dao.ProjectDAO;
import wargame.dao.ProjectInjectDAO;
import wargame.entity.Bid;
import wargame.entity.Employee;
import wargame.entity.OutsourceProject;
import wargame.entity.Player;
import wargame.entity.Project;
import wargame.entity.ProjectInject;

/**
 *
 * @author stanley.2007
 */
@Controller
@RequestMapping(value = "/project")
public class ProjectController {

    @RequestMapping(value = "/bidProjects", method = RequestMethod.GET)
    public ModelAndView viewProjectBids(@RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();

        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        ArrayList<Project> project_list = new ArrayList<Project>();
        project_list = ProjectDAO.retrieveAllBidableProjects();

        ArrayList<OutsourceProject> outsource_project_list = new ArrayList<OutsourceProject>();
        outsource_project_list = OutsourceProjectDAO.retrieveAll();

        ArrayList<Bid> player_bid_list = new ArrayList<Bid>();
        player_bid_list = BidDAO.retrieveAllBidsOfPlayer(player.getPlayer_id());

        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("project_list", project_list);
        mv.addObject("outsource_project_list", outsource_project_list);
        mv.addObject("player_bid_list", player_bid_list);
        if (announcement != null) {
            mv.addObject("announcement", announcement);
        }
        mv.setViewName("project_bid");
        return mv;
    }

    @RequestMapping(value = "/view", method = RequestMethod.GET)
    public ModelAndView viewPlayerProjects(@RequestParam(value = "announcement", required = false) String announcement,
            Model model, HttpServletRequest request) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();

        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        ArrayList<Project> project_list = ProjectDAO.retrievePlayerProjects(player.getPlayer_id());

        ArrayList<OutsourceProject> outsource_project_list = OutsourceProjectDAO.retrievePlayerProjects(player.getPlayer_id());

        ArrayList<OutsourceProject> player_generated_outsource_projects = new ArrayList<OutsourceProject>();

        for (Project project : project_list) {

            // check if the project can be submitted already
            project.setSubmitable(ManageProject.isProjectSubmitable(project.getProject_id()));

            ProjectInject inject = ProjectInjectDAO.findForTurn(project.getProject_id(), GameTurn.current_turn);
            if (inject != null) {
                project.setInject(inject);
            }

            ArrayList<OutsourceProject> project_outsourced_list = new ArrayList<OutsourceProject>();
            project_outsourced_list = OutsourceProjectDAO.retrieveAllOutsourceProjectOfProject(project.getProject_id());
            for (OutsourceProject op : project_outsourced_list) {
                player_generated_outsource_projects.add(op);
            }
        }

        for (OutsourceProject op : outsource_project_list) {
            op.setSubmitable(ManageProject.isOutsourcedProjectSubmitable(op.getProject_id()));
        }

        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("project_list", project_list);
        mv.addObject("outsource_project_list", outsource_project_list);
        mv.addObject("player_generated_outsource_projects", player_generated_outsource_projects);

        if (announcement != null) {
            mv.addObject("announcement", announcement);
        }
        mv.setViewName("project");
        return mv;
    }

    @RequestMapping(value = "/{project_id}/bid", method = RequestMethod.POST)
    public ModelAndView bidProject(HttpServletRequest request, HttpServletResponse response,
            @RequestParam(value = "project_id") Integer project_id,
            @RequestParam(value = "parent_id", required = false) Integer parent_id, Model model) {

        ModelAndView mv = new ModelAndView();

        // check if the game is paused.
        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/bidProjects");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        Player p = ManagePlayer.getThisPlayer(request);

        String announcement = "";

        // check if player bidding for project or outsource project
        if (parent_id == null) {
            // bid for project, add player bid

            // get project bid
            Project project = ProjectDAO.retrieveProject(project_id);
            int project_bid = Integer.parseInt(request.getParameter(Integer.toString(project_id)));

            // is the bid bigger than the maximum bid
            if (project_bid <= project.getMax_bid()) {
                if(project_bid >= project.getMax_bid()*0.5){
                    String status = ManageBid.addABid(p.getPlayer_id(), project_id, project_bid);
                    if (status.equals("success")) {
                        announcement = "successfully submitted bid for the project #" + project_id;
                    }

                    else {
                        announcement = "fails to submit bid for project #" + project_id + ". " + status;
                    }
                }
                else{
                      announcement = "Bid amount too little. You need to bid at least 50% of the max bid for the project #" + project_id;
                }

            } else {
                // the bid is bigger than the maximum bid! display error!
                announcement = "fails to submit bid for project #" + project_id + ". The bid cannot exceed maximum bid ";
            }
        } else {
            // purchase outsource project
            OutsourceProject op = OutsourceProjectDAO.retrieveOutsourceProject(project_id);

            Analytic.createTakeOutsourceProjectAnalytic(p.getPlayer_id());

            op.setTaken_by(p.getPlayer_id());
            OutsourceProjectDAO.updateOutsourceProject(op);

            announcement = "successfully purchased outsource project #" + project_id;
        }

        mv.addObject("announcement", announcement);
        mv.setViewName("redirect:/servlet/project/bidProjects");

        return mv;
    }

    @RequestMapping(value = "/{project_id}/editBid", method = RequestMethod.POST)
    public ModelAndView editBid(HttpServletRequest request, HttpServletResponse response,
            @RequestParam(value = "project_id") Integer project_id, Model model) {

        ModelAndView mv = new ModelAndView();

        // check if the game is paused.
        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/bidProjects");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        Player p = ManagePlayer.getThisPlayer(request);

        int project_bid = Integer.parseInt(request.getParameter(Integer.toString(project_id)));

        String announcement;
        String status = ManageBid.editBid(p.getPlayer_id(), project_id, project_bid);
        if (status.equals("success")) {
            announcement = "successfully edited bid for the project #" + project_id;
        } else {
            announcement = "fails to edit bid for project #" + project_id + ". " + status;
        }

        mv.addObject("announcement", announcement);
        mv.setViewName("redirect:/servlet/project/bidProjects");

        return mv;
    }

    @RequestMapping(value = "/{project_id}/removeBid", method = RequestMethod.GET)
    public ModelAndView removeBid(HttpServletRequest request, HttpServletResponse response,
            @PathVariable(value = "project_id") Integer project_id, Model model) {

        ModelAndView mv = new ModelAndView();

        // check if the game is paused.
        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/bidProjects");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        Player p = ManagePlayer.getThisPlayer(request);

        String announcement;
        if (ManageBid.removeBid(p.getPlayer_id(), project_id)) {
            announcement = "successfully removed bid for the project #" + project_id;
        } else {
            announcement = "fails to remove bid for project #" + project_id;
        }

        mv.addObject("announcement", announcement);
        mv.setViewName("redirect:/servlet/project/bidProjects");

        return mv;
    }

    @RequestMapping(value = "/{project_id}/assign", method = RequestMethod.GET)
    public ModelAndView assignProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();

        // check if the game is paused.
        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        // get the project
        Project project = ProjectDAO.retrieveProject(project_id);

        // get all player employees
        ArrayList<Employee> temp_employee_list = EmployeeDAO.retrievePlayerEmployees(player);
        ArrayList<Employee> employee_list = new ArrayList<Employee>();
        String employee_ids = "";

        // filter out based on the project need + employee's competencies and availability
        for (int i = 0; i < temp_employee_list.size(); i++) {
            Employee temp = temp_employee_list.get(i);
            if (project.getMan_hours_c_sharp() > 0 && temp.getSkillPoints_c_sharp() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_dot_net() > 0 && temp.getSkillPoints_dot_net() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_jsp() > 0 && temp.getSkillPoints_jsp() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_php() > 0 && temp.getSkillPoints_php() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_ruby() > 0 && temp.getSkillPoints_ruby() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_mysql() > 0 && temp.getSkillPoints_mysql() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_mssql() > 0 && temp.getSkillPoints_mssql() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_oracle() > 0 && temp.getSkillPoints_oracle() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            }
        }

        mv.setViewName("project_assign");
        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("employee_list", employee_list);
        mv.addObject("employee_ids", employee_ids);
        mv.addObject("project", project);
        if (announcement != null) {
            mv.addObject("announcement", announcement);
        }

        return mv;
    }

    @RequestMapping(value = "/{project_id}/assign_outsource", method = RequestMethod.GET)
    public ModelAndView assignOutsourceProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();

        // check if the game is paused.
        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        // get the project
        OutsourceProject project = OutsourceProjectDAO.retrieveOutsourceProject(project_id);

        // get all player employees
        ArrayList<Employee> temp_employee_list = EmployeeDAO.retrievePlayerEmployees(player);
        ArrayList<Employee> employee_list = new ArrayList<Employee>();
        String employee_ids = "";

        // filter out based on the project need + employee's competencies and availability
        for (int i = 0; i < temp_employee_list.size(); i++) {
            Employee temp = temp_employee_list.get(i);
            if (project.getMan_hours_c_sharp() > 0 && temp.getSkillPoints_c_sharp() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_dot_net() > 0 && temp.getSkillPoints_dot_net() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_jsp() > 0 && temp.getSkillPoints_jsp() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_php() > 0 && temp.getSkillPoints_php() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_ruby() > 0 && temp.getSkillPoints_ruby() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_mysql() > 0 && temp.getSkillPoints_mysql() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_mssql() > 0 && temp.getSkillPoints_mssql() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            } else if (project.getMan_hours_oracle() > 0 && temp.getSkillPoints_oracle() > 0 && temp.getHours_remaining() > 0) {
                employee_list.add(temp);
                employee_ids += temp.getEmployee_id() + ";";
            }
        }

        mv.setViewName("project_assign");
        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("employee_list", employee_list);
        mv.addObject("employee_ids", employee_ids);
        mv.addObject("outsource", "outsource");
        mv.addObject("project", project);
        if (announcement != null) {
            mv.addObject("announcement", announcement);
        }

        return mv;
    }

    @RequestMapping(value = "/{project_id}/assign", method = RequestMethod.POST)
    public ModelAndView processAssigningProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "outsource", required = false) String outsource,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/" + project_id + "/assign");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }


        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        ArrayList<Employee> employee_list = new ArrayList<Employee>();
        String employee_ids = request.getParameter("employee_ids");
        int index = 0;

        while (employee_ids.indexOf(";", index) != -1) {
            int tempindex = employee_ids.indexOf(";", index);
            String employee_id_string = employee_ids.substring(index, tempindex);
            int employee_id = Integer.parseInt(employee_id_string);
            Employee employee = EmployeeDAO.retrieveEmployee(employee_id);
            employee_list.add(employee);
            index = tempindex + 1;
        }

        // get the project
        Project project = ProjectDAO.retrieveProject(project_id);

        // get the list of updated business location details
        Enumeration enumeration = request.getParameterNames();

        // get all the parameters value submitted from the form
        // required! because textbox (parameter) are dynamically generated
        while (enumeration.hasMoreElements()) {
            String parameter = (String) enumeration.nextElement();

            if (!parameter.equals("employee_ids") && !parameter.equals("outsource")) {
                // the name of parameter is in the form of
                // 'skillname' + '!' + 'employee_id'
                // e.g. oracle!12
                int tempindex = parameter.indexOf("!");
                String skill = parameter.substring(0, tempindex);
                int id = Integer.parseInt(parameter.substring(tempindex + 1, parameter.length()));
                String hour_spent_string = request.getParameter(parameter);
                if (!hour_spent_string.equals("")) {

                    int hour_spent = Integer.parseInt(hour_spent_string);

                    // assign the skill and hour to the particular employee
                    for (Employee employee : employee_list) {
                        if (employee.getEmployee_id() == id) {

                            int hour_remaining = employee.getHours_remaining();
                            // check if employee have enough remaining hours to do the work
                            if (hour_remaining < hour_spent) {
                                mv.setViewName("redirect:/servlet/project/" + project_id + "/assign");
                                mv.addObject("announcement", "employee #" + id + " do not have enough remaining hours left to do " + hour_spent + " hours of work");
                                return mv;
                            }

                            // need to get turn from the gamevariable;
                            ManageEmployee.assignEmployeeToProject(player, project, employee, skill, hour_spent, GameTurn.current_turn);
                            hour_remaining -= hour_spent;
                            employee.setHours_remaining(hour_remaining);
                            EmployeeDAO.updateEmployee(employee);

                            //function is done below
                            assignHour(employee, skill, hour_spent);
                        }
                    }
                }
            }
        }

        // deduct project hours
        for (Employee employee : employee_list) {
            int hour_dot_net = project.getMan_hours_dot_net();
            if (hour_dot_net > 0) {
                hour_dot_net -= employee.getHour_dot_net();
            }
            project.setMan_hours_dot_net(hour_dot_net);

            int hour_c_sharp = project.getMan_hours_c_sharp();
            if (hour_c_sharp > 0) {
                hour_c_sharp -= employee.getHour_c_sharp();
            }
            project.setMan_hours_c_sharp(hour_c_sharp);

            int hour_jsp = project.getMan_hours_jsp();
            if (hour_jsp > 0) {
                hour_jsp -= employee.getHour_jsp();
            }
            project.setMan_hours_jsp(hour_jsp);

            int hour_php = project.getMan_hours_php();
            if (hour_php > 0) {
                hour_php -= employee.getHour_php();
            }
            project.setMan_hours_php(hour_php);

            int hour_ruby = project.getMan_hours_ruby();
            if (hour_ruby > 0) {
                hour_ruby -= employee.getHour_ruby();
            }
            project.setMan_hours_ruby(hour_ruby);

            int hour_mysql = project.getMan_hours_mysql();
            if (hour_mysql > 0) {
                hour_mysql -= employee.getHour_mysql();
            }
            project.setMan_hours_mysql(hour_mysql);

            int hour_mssql = project.getMan_hours_mssql();
            if (hour_mssql > 0) {
                hour_mssql -= employee.getHour_mssql();
            }
            project.setMan_hours_mssql(hour_mssql);

            int hour_oracle = project.getMan_hours_oracle();
            if (hour_oracle > 0) {
                hour_oracle -= employee.getHour_oracle();
            }
            project.setMan_hours_oracle(hour_oracle);
        }

        // update project
        ProjectDAO.updateProject(project);

        mv.setViewName("project_assign_result");
        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("employee_list", employee_list);
        mv.addObject("project", project);

        return mv;
    }

    @RequestMapping(value = "/{project_id}/assign_outsource", method = RequestMethod.POST)
    public ModelAndView processAssigningOutsourceProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "outsource", required = false) String outsource,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/" + project_id + "/assign_outsoure");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }


        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        ArrayList<Employee> employee_list = new ArrayList<Employee>();
        String employee_ids = request.getParameter("employee_ids");
        int index = 0;

        while (employee_ids.indexOf(";", index) != -1) {
            int tempindex = employee_ids.indexOf(";", index);
            String employee_id_string = employee_ids.substring(index, tempindex);
            int employee_id = Integer.parseInt(employee_id_string);
            Employee employee = EmployeeDAO.retrieveEmployee(employee_id);
            employee_list.add(employee);
            index = tempindex + 1;
        }

        // get the project
        OutsourceProject project = OutsourceProjectDAO.retrieveOutsourceProject(project_id);

        // get the list of updated business location details
        Enumeration enumeration = request.getParameterNames();

        // get all the parameters value submitted from the form
        // required! because textbox (parameter) are dynamically generated
        while (enumeration.hasMoreElements()) {
            String parameter = (String) enumeration.nextElement();

            if (!parameter.equals("employee_ids") && !parameter.equals("outsource")) {
                // the name of parameter is in the form of
                // 'skillname' + '!' + 'employee_id'
                // e.g. oracle!12
                int tempindex = parameter.indexOf("!");
                String skill = parameter.substring(0, tempindex);
                int id = Integer.parseInt(parameter.substring(tempindex + 1, parameter.length()));
                String hour_spent_string = request.getParameter(parameter);
                if (!hour_spent_string.equals("")) {

                    int hour_spent = Integer.parseInt(hour_spent_string);

                    // assign the skill and hour to the particular employee
                    for (Employee employee : employee_list) {
                        if (employee.getEmployee_id() == id) {

                            int hour_remaining = employee.getHours_remaining();
                            // check if employee have enough remaining hours to do the work
                            if (hour_remaining < hour_spent) {
                                mv.setViewName("redirect:/servlet/project/" + project_id + "/assign_outsource");
                                mv.addObject("announcement", "employee #" + id + " do not have enough remaining hours left to do " + hour_spent + " hours of work");
                                return mv;
                            }

                            // need to get turn from the gamevariable;
                            ManageEmployee.assignEmployeeToProject(player, project, employee, skill, hour_spent, GameTurn.current_turn);
                            hour_remaining -= hour_spent;
                            employee.setHours_remaining(hour_remaining);
                            EmployeeDAO.updateEmployee(employee);

                            //function is done below
                            assignHour(employee, skill, hour_spent);
                        }
                    }
                }
            }
        }

        // deduct project hours
        for (Employee employee : employee_list) {
            int hour_dot_net = project.getMan_hours_dot_net();
            if (hour_dot_net > 0) {
                hour_dot_net -= employee.getHour_dot_net();
            }
            project.setMan_hours_dot_net(hour_dot_net);

            int hour_c_sharp = project.getMan_hours_c_sharp();
            if (hour_c_sharp > 0) {
                hour_c_sharp -= employee.getHour_c_sharp();
            }
            project.setMan_hours_c_sharp(hour_c_sharp);

            int hour_jsp = project.getMan_hours_jsp();
            if (hour_jsp > 0) {
                hour_jsp -= employee.getHour_jsp();
            }
            project.setMan_hours_jsp(hour_jsp);

            int hour_php = project.getMan_hours_php();
            if (hour_php > 0) {
                hour_php -= employee.getHour_php();
            }
            project.setMan_hours_php(hour_php);

            int hour_ruby = project.getMan_hours_ruby();
            if (hour_ruby > 0) {
                hour_ruby -= employee.getHour_ruby();
            }
            project.setMan_hours_ruby(hour_ruby);

            int hour_mysql = project.getMan_hours_mysql();
            if (hour_mysql > 0) {
                hour_mysql -= employee.getHour_mysql();
            }
            project.setMan_hours_mysql(hour_mysql);

            int hour_mssql = project.getMan_hours_mssql();
            if (hour_mssql > 0) {
                hour_mssql -= employee.getHour_mssql();
            }
            project.setMan_hours_mssql(hour_mssql);

            int hour_oracle = project.getMan_hours_oracle();
            if (hour_oracle > 0) {
                hour_oracle -= employee.getHour_oracle();
            }
            project.setMan_hours_oracle(hour_oracle);
        }

        // update project
        OutsourceProjectDAO.updateOutsourceProject(project);

        mv.setViewName("project_assign_result");
        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("employee_list", employee_list);
        mv.addObject("project", project);

        return mv;
    }

    // assign the total hours spent by the employee
    // formula: skill level * hours spent
    private void assignHour(Employee employee, String skill, int hour) {
        if (skill.equals("dot_net")) {
            hour *= employee.getSkillPoints_dot_net();
            employee.setHour_dot_net(hour);
        } else if (skill.equals("c_sharp")) {
            hour *= employee.getSkillPoints_c_sharp();
            employee.setHour_c_sharp(hour);
        } else if (skill.equals("jsp")) {
            hour *= employee.getSkillPoints_jsp();
            employee.setHour_jsp(hour);
        } else if (skill.equals("php")) {
            hour *= employee.getSkillPoints_php();
            employee.setHour_php(hour);
        } else if (skill.equals("ruby")) {
            hour *= employee.getSkillPoints_ruby();
            employee.setHour_ruby(hour);
        } else if (skill.equals("mysql")) {
            hour *= employee.getSkillPoints_mysql();
            employee.setHour_mysql(hour);
        } else if (skill.equals("mssql")) {
            hour *= employee.getSkillPoints_mssql();
            employee.setHour_mssql(hour);
        } else if (skill.equals("oracle")) {
            hour *= employee.getSkillPoints_oracle();
            employee.setHour_oracle(hour);
        }
    }

    @RequestMapping(value = "/{project_id}/outsource", method = RequestMethod.GET)
    public ModelAndView outsourceProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        // get the project
        Project project = ProjectDAO.retrieveProject(project_id);

        mv.setViewName("project_outsource");
        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("project", project);
        if (announcement != null) {
            mv.addObject("announcement", announcement);
        }

        return mv;
    }

    // Outsource Project
    @RequestMapping(value = "/{project_id}/outsource", method = RequestMethod.POST)
    public ModelAndView outsourceProjects(
            @PathVariable(value = "project_id") int parent_id,
            @RequestParam(value = "dot_net", required = false) Integer dot_net,
            @RequestParam(value = "c_sharp", required = false) Integer c_sharp,
            @RequestParam(value = "jsp", required = false) Integer jsp,
            @RequestParam(value = "php", required = false) Integer php,
            @RequestParam(value = "ruby", required = false) Integer ruby,
            @RequestParam(value = "mysql", required = false) Integer mysql,
            @RequestParam(value = "mssql", required = false) Integer mssql,
            @RequestParam(value = "oracle", required = false) Integer oracle,
            @RequestParam(value = "price", required = true) Integer price,
            @RequestParam(value = "due_turn", required = true) Integer due_turn,
            HttpServletRequest request, Model model) {

        ModelAndView mv = new ModelAndView();

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/" + parent_id + "/outsource");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }


        Player player = ManagePlayer.getThisPlayer(request);
        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        boolean hasError = false;
        String error_message = "";
        Project p = ProjectDAO.retrieveProject(parent_id);

        Integer[] skills = new Integer[8];
        skills[GlobalConstant.DOT_NET] = dot_net;
        skills[GlobalConstant.C_SHARP] = c_sharp;
        skills[GlobalConstant.JSP] = jsp;
        skills[GlobalConstant.PHP] = php;
        skills[GlobalConstant.RUBY] = ruby;
        skills[GlobalConstant.MYSQL] = mysql;
        skills[GlobalConstant.MSSQL] = mssql;
        skills[GlobalConstant.ORACLE] = oracle;

        for (int k = 0; k < skills.length; k++) {
            if (skills[k] != null && (skills[k] < 0 || skills[k] > p.getManhourBySkill(k))) {
                // Not within range
                hasError = true;
                error_message += p.getManhourSkillName(k) + " man hours not in range, ";
            }
        }

        if (price < 0) {
            //Price entered is lesser than 0
            hasError = true;
            error_message += "Invalid price entered";
        }

        if (due_turn <= GameTurn.current_turn) {
            // Turn entered has passed.
            hasError = true;
            error_message += "Turn entered has passed";
        }


        if (!hasError) {

            // yes, add new outsource project
            OutsourceProject op = new OutsourceProject();
            op.setParent_id(parent_id);
            for (int k = 0; k < skills.length; k++) {
                op.setManhourBySkill(k, skills[k]);
            }
            op.setBidded_price(price);
            op.setDue_turn(due_turn);
            op.setOffered_by(player.getPlayer_id());
            op.setTrack_record_point(0);
            int project_id = OutsourceProjectDAO.insertOutsourceProject(op);

            if (project_id > 0) { // outsourced project created
                for (int k = 0; k < skills.length; k++) {
                    if (skills[k] != null) {
                        p.setManhourBySkill(k, p.getManhourBySkill(k) - skills[k]);
                    }
                }

                ProjectDAO.updateProject(p);

                mv.setViewName("redirect:/servlet/project/view");
                mv.addObject("announcement", "successfully created an outsource project for project #" + parent_id);
            } else {
                // It shouldn't fall into here at all, if it falls into here it means database got problem
                mv.setViewName("redirect:/servlet/project/" + parent_id + "/outsource");
                mv.addObject("announcement", error_message);
            }

        } else {
            // Return saying have error
            mv.setViewName("redirect:/servlet/project/" + parent_id + "/outsource");
            mv.addObject("announcement", error_message);
        }

        return mv;
    }

    @RequestMapping(value = "/{parent_id}/edit_outsource", method = RequestMethod.GET)
    public ModelAndView editOutsourceProject(@PathVariable("parent_id") int parent_id,
            @RequestParam(value = "project_id", required = true) int project_id,
            @RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        // get the project
        Project project = ProjectDAO.retrieveProject(parent_id);
        OutsourceProject outsource_project = OutsourceProjectDAO.retrieveOutsourceProject(project_id);

        if (outsource_project.getTaken_by() > 0) {
            // too late to change.
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "the outsource project is already taken by other player, too late to change now");
            return mv;
        }

        for (int k = 0; k < 8; k++) {
            // revert the project manhours remaining.
            project.setManhourBySkill(k, project.getManhourBySkill(k) + outsource_project.getManhourBySkill(k));
        }

        mv.setViewName("project_outsource");
        mv.addObject("player", player);
        mv.addObject("turn", GameTurn.getTurnInfo());
        mv.addObject("project", project);
        mv.addObject("outsource_project", outsource_project);
        if (announcement != null) {
            mv.addObject("announcement", announcement);
        }

        return mv;
    }

    // Edit Outsource Project
    @RequestMapping(value = "/{parent_id}/edit_outsource", method = RequestMethod.POST)
    public ModelAndView editOutsourceProjects(
            @PathVariable(value = "parent_id") Integer parent_id,
            @RequestParam(value = "project_id", required = true) Integer project_id,
            @RequestParam(value = "dot_net", required = false) Integer dot_net,
            @RequestParam(value = "c_sharp", required = false) Integer c_sharp,
            @RequestParam(value = "jsp", required = false) Integer jsp,
            @RequestParam(value = "php", required = false) Integer php,
            @RequestParam(value = "ruby", required = false) Integer ruby,
            @RequestParam(value = "mysql", required = false) Integer mysql,
            @RequestParam(value = "mssql", required = false) Integer mssql,
            @RequestParam(value = "oracle", required = false) Integer oracle,
            @RequestParam(value = "price", required = true) Integer price,
            @RequestParam(value = "due_turn", required = true) Integer due_turn,
            HttpServletRequest request, Model model) {

        ModelAndView mv = new ModelAndView();

        Player player = ManagePlayer.getThisPlayer(request);
        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        boolean hasError = false;
        String error_message = "";
        Project p = ProjectDAO.retrieveProject(parent_id);
        OutsourceProject op = OutsourceProjectDAO.retrieveOutsourceProject(project_id);

        if (op.getTaken_by() > 0) {
            // too late to change.
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "the outsource project is already taken by other player, too late to change now");
            return mv;
        }

        Integer[] skills = new Integer[8];
        skills[GlobalConstant.DOT_NET] = dot_net;
        skills[GlobalConstant.C_SHARP] = c_sharp;
        skills[GlobalConstant.JSP] = jsp;
        skills[GlobalConstant.PHP] = php;
        skills[GlobalConstant.RUBY] = ruby;
        skills[GlobalConstant.MYSQL] = mysql;
        skills[GlobalConstant.MSSQL] = mssql;
        skills[GlobalConstant.ORACLE] = oracle;

        for (int k = 0; k < 8; k++) {
            // revert the project manhours remaining.
            p.setManhourBySkill(k, p.getManhourBySkill(k) + op.getManhourBySkill(k));
        }

        for (int k = 0; k < skills.length; k++) {
            if (skills[k] != null && (skills[k] < 0 || skills[k] > p.getManhourBySkill(k))) {
                // Not within range
                hasError = true;
                error_message += p.getManhourSkillName(k) + " man hours not in range, ";
            }
        }

        if (price < 0) {
            //Price entered is lesser than 0
            hasError = true;
            error_message += "Invalid price entered";
        }

        if (due_turn < GameTurn.current_turn) {
            // Turn entered has passed.
            hasError = true;
            error_message += "Turn entered has passed";
        }


        if (!hasError) {

            if (op.getTaken_by() > 0) {
                // too late to change.
                error_message += "the outsource project is already taken by other player, too late to change now";
            } else {
                for (int k = 0; k < skills.length; k++) {
                    op.setManhourBySkill(k, skills[k]);
                }
                op.setBidded_price(price);
                op.setDue_turn(due_turn);
                op.setTrack_record_point(0);
                OutsourceProjectDAO.updateOutsourceProject(op);

                // then deduct the project hours
                for (int k = 0; k < skills.length; k++) {
                    if (skills[k] != null) {
                        p.setManhourBySkill(k, p.getManhourBySkill(k) - skills[k]);
                    }
                }

                ProjectDAO.updateProject(p);

                mv.setViewName("redirect:/servlet/project/view");
                mv.addObject("announcement", "successfully edited outsource project #" + project_id);
            }

        } else {
            // Return saying have error
            mv.setViewName("redirect:/servlet/project/" + parent_id + "/edit_outsource");
            mv.addObject("announcement", error_message);
        }

        return mv;
    }

    @RequestMapping(value = "/{parent_id}/cancel_outsource", method = RequestMethod.GET)
    public ModelAndView cancelOutsourceProject(@PathVariable("parent_id") int parent_id,
            @RequestParam(value = "project_id", required = true) int project_id,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        // get the project
        Project project = ProjectDAO.retrieveProject(parent_id);
        OutsourceProject outsource_project = OutsourceProjectDAO.retrieveOutsourceProject(project_id);

        if (outsource_project.getTaken_by() > 0) {
            // set the condition of cancel penalty
            String announcement = "You have successfully canceled your outsource project";

            int penalty = 0;
            if (outsource_project.getDue_turn() >= GameTurn.current_turn) {
                penalty = outsource_project.getBidded_price();
                if (player.getBalance() < penalty) {
                    mv.setViewName("redirect:/servlet/project/view");
                    mv.addObject("announcement", "Fails to cancel project. Insufficient fund to pay penalty");
                    return mv;
                }
                int bidder_id = outsource_project.getTaken_by();
                Player bidder = PlayerDAO.retrievePlayer(bidder_id);

                bidder.addBalance(penalty);
                player.deductBalance(penalty);

                PlayerDAO.updatePlayer(player);
                PlayerDAO.updatePlayer(bidder);

                announcement += "penalty :" + outsource_project.getBidded_price_string();
            }

            OutsourceProjectDAO.deleteOutsourceProject(project_id);

            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", announcement);
            return mv;
        }

        for (int k = 0; k < 8; k++) {
            // revert the project manhours remaining.
            project.setManhourBySkill(k, project.getManhourBySkill(k) + outsource_project.getManhourBySkill(k));
        }

        OutsourceProjectDAO.deleteOutsourceProject(project_id);
        ProjectDAO.updateProject(project);

        mv.setViewName("redirect:/servlet/project/view");
        mv.addObject("announcement", "Successfully deleted outsource project #" + project_id);

        return mv;
    }

    @RequestMapping(value = "/{project_id}/submit", method = RequestMethod.GET)
    public ModelAndView submitProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        // submit the project
        ManageProject.submitProject(project_id);

        mv.setViewName("redirect:/servlet/project/view");
        mv.addObject("announcement", "Successfully submitted project #" + project_id + ". New balance: " + player.getBalance_string());

        return mv;
    }

    @RequestMapping(value = "/{project_id}/submit_outsource", method = RequestMethod.GET)
    public ModelAndView submitOutsourceProject(@PathVariable("project_id") int project_id,
            @RequestParam(value = "announcement", required = false) String announcement,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        // submit the project
        ManageProject.submitOutsourcedProject(project_id);
        OutsourceProject project = OutsourceProjectDAO.retrieveOutsourceProject(project_id);
        int balance = player.getBalance();
        balance += project.getBidded_price();
        player.setBalance(balance);

        mv.setViewName("redirect:/servlet/project/view");
        mv.addObject("announcement", "Successfully submitted outsource project #" + project_id + ". New balance: " + player.getBalance_string());

        return mv;
    }
    
    @RequestMapping(value = "/{project_id}/accept_inject", method = RequestMethod.GET)
    public ModelAndView acceptInject(@PathVariable("project_id") int project_id,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        ProjectInject inject = ProjectInjectDAO.findById(project_id);
        Project project = ProjectDAO.retrieveProject(project_id);

        for(int i =0; i<8; i++){
            int value = inject.getManhourBySkill(i);
            project.addManhourBySkill(i, value);
        }

        int price =project.getBidded_price();
        price += inject.getPrice();
        project.setBidded_price(price);

        ProjectDAO.updateProject(project);
        ProjectInjectDAO.delete(project_id);

        mv.setViewName("redirect:/servlet/project/view");
        mv.addObject("announcement", "Accepted change of scope for project #" + project_id);

        return mv;
    }

    @RequestMapping(value = "/{project_id}/decline_inject", method = RequestMethod.GET)
     public ModelAndView declineInject(@PathVariable("project_id") int project_id,
            HttpServletRequest request, Model model) {
        // model refer to object to pass to this page
        // check index.jsp for the ${username}
        ModelAndView mv = new ModelAndView();
        Player player = ManagePlayer.getThisPlayer(request);

        if (GameTurn.game_pause) {
            mv.setViewName("redirect:/servlet/project/view");
            mv.addObject("announcement", "game is paused. no actions is allowed");
            return mv;
        }

        if (player == null) {
            mv.setViewName("register");
            return mv;
        }

        ProjectInjectDAO.delete(project_id);

        mv.setViewName("redirect:/servlet/project/view");
        mv.addObject("announcement", "Decline change of scope for project #" + project_id);

        return mv;
    }


}
